package com.example.learningspringboot.controller;

import com.example.learningspringboot.service.AspectService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Aspect 切面的测试控制器，展示如何使用切面
 * 1.我们要创建一个业务类AspectService
 * 2.创建一个切片类AuthAspect
 * 3.然后调用业务类AspectService的方法getUser()，这样就调用到代理对象
 */
@RestController
@RequestMapping("/testAspect")
public class TestAspectController {

    /**
     * 在Bean的依赖注入上使用的构造函数方式,依赖注入的Bean对象使用final来修饰;
     *下面是这样做的原因:
     * 1.不可变性 (Immutability)
     * 优势:一旦在构造函数中赋值，就不能再被修改,防止在类的其他方法中意外重新赋值,确保依赖关系在整个对象生命周期中保持一致
     * 2.线程安全，具体需要DeepSeek
     * 3.明确的设计意图
     * 4.编译时检查,如果没有初始化final字段，编译器会报错,如果忘记这行赋值，编译错误：variable productRepository might not have been initialized
     * 5.与Spring框架的协作
     * 6.防止NPE（空指针异常），我们可以在构造函数赋值的时候进行null检查
     * 7.函数式编程风格
     * 8.与记录类（Record）的兼容性
     * 总结:
     * 使用final修饰注入的bean是Spring开发中的最佳实践，因为它：
     * ✅ 增强安全性：防止意外修改依赖
     * ✅ 提高可读性：明确表达设计意图
     * ✅ 支持线程安全：天然的不可变对象
     * ✅ 便于测试：依赖关系明确且稳定
     * ✅ 编译时保障：编译器帮助检查初始化
     * ✅ 符合函数式编程原则：鼓励不可变性
     */
    private final AspectService aspectService;

    /**
     * 这里我们使用的构造函数进行依赖注入
     * 在单一构造函数下可省略
     */
    @Autowired
    public TestAspectController(AspectService aspectService) {
        this.aspectService = aspectService;
    }

    @GetMapping("/test")
    public String test() {
        aspectService.getUser();
        System.out.println("---------------------------");
        aspectService.addUser();
        return "success";
    }
}
